﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using DG.Common.Patterns.Commands;
using DG.Common.Patterns.MVVM;
using TCC.ControleFluxoDeCaixa.Apresentacao.Views;
using TCC.ControleFluxoDeCaixa.Model.Entities;
using TCC.ControleFluxoDeCaixa.Model.Fluxo;
using TCC.ControleFluxoDeCaixa.Model.Fluxo.Credito;
using TCC.ControleFluxoDeCaixa.Model.Gerenciadores;

namespace TCC.ControleFluxoDeCaixa.Apresentacao.ViewModels.Credito
{
    public class GerenciadorCartaoDeCreditoWindowViewModel : ViewModelBase
    {
        private readonly FluxoDeCaixaContextFiltrado _context;
        private ContaCredito _contaCredito;
        private FaturaCreditoResumo _selectedFatura;
        private decimal _juros;

        public GerenciadorCartaoDeCreditoWindowViewModel(FluxoDeCaixaContextFiltrado context)
        {
            _context = context;
        }

        public ContaCredito ContaCredito
        {
            get { return _contaCredito; }
            set
            {
                if (Equals(value, _contaCredito)) return;
                _contaCredito = value;
                OnPropertyChanged("ContaCredito");
                OnPropertyChanged("SaldoLimite");
                OnPropertyChanged("SaldoAtualDisponivel");
                OnPropertyChanged("SaldoRestante");
                OnPropertyChanged("SaldoUtilizado");
                OnPropertyChanged("LimiteUltrapassado");
                OnPropertyChanged("TotalNaoPagoCartao");
                OnPropertyChanged("GetFaturasCredito");
            }
        }

        public decimal SaldoLimite
        {
            get { return ContaCredito != null ? ContaCredito.ValorLimite : 0; }
        }

        public decimal SaldoAtualDisponivel
        {
            get
            {
                if (ContaCredito != null)
                {
                    if (_context.Movimentos.Count() !=0)
                    {
                        return SaldoLimite - SaldoUtilizado;    
                    }
                    
                }
                return 0;
            }
        }

        public decimal SaldoUtilizado
        {
            get
            {
                return ContaCredito == null ? 0 : -(_context.Movimentos
                    .Where(m => m.Conta.ContaFinanceiraId == ContaCredito.ContaFinanceiraId)
                    .Sum(m => (decimal?)((int)m.TipoDeMovimento) * m.ValorAbsoluto) ?? 0);
            }
        }

        public decimal SaldoRestante
        {
            get
            {
                if (ContaCredito != null)
                {
                    return (SaldoLimite - SaldoUtilizado);
                }
                return 0;
            }
        }        
        public string LimiteUltrapassado
        {
            get
            {
                if (ContaCredito != null && SaldoAtualDisponivel <= 0)
                {
                    return "Sim";
                }
                return "Não";
            }
        }
        public decimal TotalNaoPagoCartao
        {
            get
            {

                if (ContaCredito != null && SaldoAtualDisponivel > 0)
                {
                    return (-1) * (_context.Movimentos
                        .Where(c => c.Conta.ContaFinanceiraId == ContaCredito.ContaFinanceiraId)
                        .Sum(m => (decimal?)((int)m.TipoDeMovimento) * m.ValorAbsoluto) ?? 0);
                }
                return 0;
            }
        }
        public decimal Juros
        {
            get { return _juros; }
            set
            {
                if (value == _juros) return;
                _juros = value;
                OnPropertyChanged("Juros");
            }
        }

        public IEnumerable<ContaCredito> GetContasCredito
        {
            get { return _context.ContasCredito.ToArray();}
        }

        public IEnumerable<FaturaCreditoResumo> GetFaturasCredito
        {
            get
            {
               
                if (ContaCredito == null) return null;

                var movsPag = _context.FaturasCredito.ToArray()
                    .ToDictionary(c => c, c => c.LancamentoPagamento.Movimentos);
                
                var movimentosAgrupadosPorData =  ContaCredito.Movimentos.Except(movsPag.SelectMany(c => c.Value))
                    .GroupBy(c => c.DataDoMovimento.Date.AddDays(-ContaCredito.QtdDiasPeriodoFechamento))
                    .OrderBy(c => c.Key).ToArray();

                var list = new List<FaturaCreditoResumo>();
                FaturaCreditoResumo fatAnterior = null;
                foreach (var movimentos in movimentosAgrupadosPorData)
                {
                    var listaFinal = movimentos.ToArray();
                    var fat = movsPag.SingleOrDefault(c=> c.Key.Ano == movimentos.Key.Year 
                                      && c.Key.Mes == movimentos.Key.Month);
                    if (fat.Key != null)
                    {
                        
                        listaFinal = movimentos.Concat(fat.Value).ToArray(); 
                    }
                    
                    fatAnterior = new FaturaCreditoResumo(ContaCredito, movimentos.Key.Month, 
                        movimentos.Key.Year,
                        listaFinal, fatAnterior);
                    list.Add(fatAnterior);
                }
                return list;
            }
        }

        public FaturaCreditoResumo SelectedFatura
        {
            get { return _selectedFatura; }
            set
            {
                if (Equals(value, _selectedFatura)) return;
                _selectedFatura = value;
                OnPropertyChanged("SelectedFatura");
            }
        }
        public ICommand AbrirTelaPagamentoFatura
        {
            get
            {
                return new FunctionalCommand(() =>
                {
                    var vm = new PagamentoFaturaWindowViewModel(SelectedFatura, _context);
                    var telaPag = new PagamentoFaturaWindow(vm);
                    telaPag.Show();
                }, () => SelectedFatura != null);
            }
        }
        public ICommand LancarJuros
        {
            get
            {
                return new FunctionalCommand(() =>
                {
                    var lancamento = new Lancamento
                    {
                        Categoria = _context.GetCategoriaJurosCartao(),
                        DataDoLancamento = SelectedFatura.DataVencimento,
                        Usuario = SelectedFatura.ContaCredito.Usuario
                    };
                    var movimento = new Movimento
                    {
                        Conta = SelectedFatura.ContaCredito,
                        DataDoMovimento = SelectedFatura.DataVencimento,
                        Historico = "Lançamento de Juros",
                        TipoDeMovimento = TipoDeMovimento.Despesa,
                        ValorAbsoluto = Juros
                    };
                    lancamento.Movimentos.Add(movimento);
                    _context.Lancamentos.Add(lancamento);
                    _context.SaveChanges();
                    SendMessage("Juros lançados com sucesso");
                }, () => SelectedFatura != null && SelectedFatura.Fatura == null && Juros != 0);
            }
        }
    }
}
